Skip to content

Collisions, pillars and their octomap, tether task, ground go_to, config folders, student README - #2

Merged
KhAlamdar11 merged 13 commits into
masterfrom
map-collisions
Oct 29, 2026
Merged

KhAlamdar11 merged 13 commits into
masterfrom
map-collisions

Conversation

@KhAlamdar11

Copy link
Copy Markdown
Member

Summary

  • Collisions (2D): robots stop at the map (octomap voxels in sim.collision_z, flattened), at pillars, and ground robots at each other. Drones are blocked at any height and don't collide with ground robots or each other. One switch: sim.collision.
  • Pillars: a top-level obstacles: list, {x, y, radius, height}. They block the robots and the tether object, are published latched on /hero_sim/obstacles, and are turned into an octomap that octomap_server serves like a .bt map (same topics, same look in RViz). A scenario has sim.map or obstacles:, not both.
  • Tether task: winch → pulley on a UGV → ring on a UAV → object on the floor, with winch and object topics. Ready scenario: config/tether/tether_demo.yaml.
  • Ground robots: /<name>/go_to (crazyflie_interfaces/srv/GoTo), held to the speed limits; omni drives straight, diff turns-drives-turns. Poses are published at the marker height.
  • Config folders: config/tether/, config/mrs/ (Crazyflie scenarios) and config/. A config is found by filename in any folder (names are unique); start.sh, the launch files and the nodes share the rules.
  • README rewritten as setup and usage instructions for students; mesh notes moved to models/README.md.
  • RViz: the octomap displays subscribe Transient Local, so the map shows whenever RViz starts.

Heads-up

  • tether.obstacles moved to the top-level obstacles:; the old key fails with a pointer to the new one.
  • Configs moved into folders. Tools that build config/<name> paths themselves need to search the folders too (e.g. hero_mrs_control_stack/sim_experiments/run_trial.py).
  • --symlink-install workspaces rebuild over the old layout as is. A plain install may keep stale copies: rm -rf build/hero_sim install/hero_sim, then build.
  • A ground go_to blocked by an obstacle or robot now waits and carries on once the way is clear; any cmd_vel cancels it.

Testing

  • 232 pytest tests in the icuas26_finals image; CI runs them without hero_mrs_msgs (3 skip).
  • Live in a container: go_to stops at a pillar and at another robot and resumes when it moves away; octomap_server loads a generated pillar map (all 6240 cells, the same topics as icuas26_1.bt); RViz under Xvfb draws the map when started after the octomap; every command in the README runs as written.

🤖 Generated with Claude Code

KhAlamdar11 and others added 13 commits October 21, 2026 23:47
UNTESTED in the running sim: unit tests and the launch smoke test pass,
but nothing has been driven against the map in RViz yet.

At startup the ground robot sim and the Crazyflie server each read the
scenario's .bt octomap directly, keep the occupied voxels overlapping
sim.collision_z (default 0.2-2.0 m: trunks and posts, not the floor,
ceilings or tree canopies) and flatten them into one 2D grid with a
precomputed clearance per cell.

Each robot is a circle of its radius (scout 0.42, herover 0.17, other
ground robots 0.3, Crazyflies 0.1; `radius:` overrides). Every move is
checked along its path and stops before the circle touches an obstacle;
height changes always go through. set_position stays an unchecked
teleport. A robot spawned inside an obstacle can only move out of it.

On by default; sim: {collision: false} turns it off.

Known conflicts with existing scenarios:
- hero_mrs_control_stack test_branch: approach points of perch_b1 and
  perch_b10 sit on icuas26_1 trunks, so drones can't reach them.
- config/herover.yaml: herover_4 spawns inside a trunk (warned at launch).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On hardware the mocap markers sit on top of the scout and herover, so
their poses report that height, not 0. The control stack adds a body-frame
dock's z to its host's z, so docks on a UGV were lower in the sim than on
hardware.

Ground robots now take pose.z, published on /<name>/pose and in the
world -> <name> TF. It defaults by model to the top of the deck in the
mesh: scout 0.227, herover 0.095, robots without a model 0. The RViz mesh
is shifted down by z so it stays on the floor.

Not run: the pytest suite (docker run interrupted). Scenario parsing was
checked on the host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A winch drags an object across the floor; the tether runs through a
pulley on a ground robot and a ring on a Crazyflie. A scenario sets it
up with an optional tether: section (config/tether_demo.yaml). Without
one, nothing extra runs.

- hero_sim/tether.py: ROS-free quasi-static model. Slack leaves the
  object, taut slides it toward the point under the UAV, it is never
  lifted, and it jams against pillars; the winch slips in both cases.
- hero_sim/tether_sim.py: node publishing /winch/* and /tether/* plus
  RViz markers, started by sim.launch.py only for a tether: section.
- config: validated tether: section, documented in README and
  example.yaml; RViz gets a Tether display.
- Tests for the model, config and node; CI smoke tests check tether_sim
  starts with a tether: section and not without one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r object

Pillars move from tether.obstacles to a top-level obstacles: list and live
in the same ObstacleMap as the octomap grid (kept as exact circles, also
with map: null). Ground robots, Crazyflies (at any height) and the tether
object all stop at the same obstacles, under the one sim.collision switch.

ground_robot_sim publishes the pillars latched on /hero_sim/obstacles
(one CYLINDER each), drawn by a new Obstacles display in sim.rviz.
tether.obstacles now fails with a pointer to the new key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every ground robot serves /<name>/go_to with crazyflie_interfaces/srv/GoTo,
the Crazyflies' type. It reaches goal x, y and yaw in `duration`, stretched
to stay within ground_max_speed and ground_max_yaw_rate (duration 0: as
fast as allowed). omni drives straight while turning; diff turns, drives,
then turns (kinematics.GroundGoTo). relative offsets x, y in the world
frame; goal.z and group_mask are ignored. Any cmd_vel cancels it, and it
stops at the map and pillars like every other move.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Under sim.collision, each ground robot's move is checked against the other
ground robots as circles of their radius, in the same pass as the map and
the pillars (ObstacleMap.move's new `others`). Robots move one after
another each tick against the others' current positions, so they never
overlap; radius 0 opts out. load() now returns an empty map without a map
or pillars, so this works in bare scenarios too.

A blocked go_to now waits where it stopped, its clock paused, and carries
on once the way clears, instead of jumping to where its schedule got to.

config/two_ugvs.yaml: two herovers and the tether demo's pillar, no tether.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… size

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Configs can sit in config/ or a folder in it: tether/ for the tether task,
mrs/ for the control stack's Crazyflie scenarios, the rest on top
(example, ground-robot-only setups). A bare filename is searched in every
folder (names are unique; two matches are an error), folder/name.yaml is
relative to config/ unless it's an existing path. Same rules in
config.find_config (launch files, nodes) and startup/_setup.sh.

setup.py installs the folders and skips the broken links a
--symlink-install build keeps to moved configs, so existing workspaces
rebuild without a clean. Tests cover both resolvers and run every config
in every folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Setup, start/stop, scenarios and folders, moving the robots, obstacles,
the tether task and troubleshooting, without the internals. Every command
in it was run against the sim. Mesh-making notes move to models/README.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds the sim_env_a / sim_env_a12 experiment scenarios, the
test_perching_full(2) and test_unperch scenarios to config/mrs/, moves
dock_hardware2 there, and makes test_perching_full2 the default. The
example scenario gets its pillar, sim.rviz the current view, and the
README's tether section the task diagram (media/tether_demo.png).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… or obstacles

With obstacles:, octomap.launch.py writes the pillars as an octomap .bt
(<tmp>/hero_sim/<config>_obstacles.bt, floor to each pillar's height, no
ground plane) and serves it with octomap_server like a sim.map, so RViz
shows the same occupied cells, projected map and topics. obstacles.write_bt
is read_bt's inverse.

Pillars take an optional height (default 2 m) for RViz and the octomap;
collisions still ignore it. A scenario sets sim.map or obstacles:, not
both: obstacles drop the default map, and setting both is an error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
README: one Maps section for the two kinds of world, a .bt map or
obstacles:, what each looks like in RViz and where the pillar map file
goes, instead of the scattered mentions.

sim.rviz: the occupied-cells displays subscribe Transient Local, as
octomap_server publishes the map once, latched. RViz started after the
octomap now still draws it, so session.yml needs no sleep before it.

example.yaml: the pillar commented out again, so the example uses the
default map.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…only

The example scenario uses its pillar (no map) again. sim.rviz hides the
pillar cylinders by default, which showed through the octomap cells; the
Obstacles display can still be ticked on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@KhAlamdar11
KhAlamdar11 merged commit 1d19899 into master Oct 29, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant